package com.demo.seckill.web;

import com.demo.seckill.service.RedPacketService;
import com.demo.utils.DoubleUtil;
import com.demo.utils.RedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.*;

/**
 * @author : YU.TAN
 * @date : 2021/10/25 14:21
 */
@Api(tags = "抢红包")
@RestController
@RequestMapping("/redPacket")
@Slf4j
public class RedPacketController {

    @Autowired
    private RedPacketService redPacketService;

    @Autowired
    RedisUtil redisUtil;

    private static int corePoolSize = Runtime.getRuntime().availableProcessors();
    /**
     * 空闲线程存活时间
     */
    private static long keepAliveTime = 10L;

    /**
     * 创建线程池  调整队列数 拒绝服务
     */
    private static ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(corePoolSize, corePoolSize + 1, keepAliveTime, TimeUnit.SECONDS
            //线程等待队列
            , new LinkedBlockingQueue<>(1000)
            //默认线程工厂
            , Executors.defaultThreadFactory()
            //线程池拒绝策略
            , new ThreadPoolExecutor.AbortPolicy());


    /**
     * 抢红包 拆红包 抢到基本能拆到
     *
     * @param redPacketId
     */
    @ApiOperation("抢红包一")
    @RequestMapping(value = "/start/one", method = RequestMethod.GET)
    public void startOne(long redPacketId) {
        //参与人数
        int skillNum = 100;

        final CountDownLatch countDownLatch = new CountDownLatch(skillNum);

        //初始化红包数量
        redisUtil.set(redPacketId + "_num", String.valueOf(10));
        //初始化红包金额
        redisUtil.set(redPacketId + "_money", String.valueOf(100 * 100));
        //初始化剩余人数，拆红包拦截
        redisUtil.set(redPacketId + "_restPeople", String.valueOf(10));

        for (int i = 1; i <= skillNum; i++) {
            int userId = i;
            Runnable task = () -> {
                Long count = redisUtil.decr(redPacketId + "_num", 1);
                if (count >= 0) {
                    Integer money = redPacketService.startOneSeckil(redPacketId, userId);
                    Double amount = DoubleUtil.divide(Double.parseDouble(String.valueOf(money)), (double) 100);
                    log.info("用户{}抢红包成功，金额：{}", userId, amount);
                } else {
                    log.info("用户{}抢红包失败", userId);
                }

                countDownLatch.countDown();
            };
            poolExecutor.execute(task);
        }
        try {
            countDownLatch.await();
            Integer restMoney = Integer.parseInt(redisUtil.get(redPacketId + "_money").toString());
            log.info("剩余金额：{}", restMoney);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 抢红包 拆红包 抢到基本能拆到
     *
     * @param redPacketId
     */
    @ApiOperation("抢红包一")
    @RequestMapping(value = "/start/two", method = RequestMethod.GET)
    public void startTwo(long redPacketId) {
        //参与人数
        int skillNum = 100;

        final CountDownLatch countDownLatch = new CountDownLatch(skillNum);

        //初始化红包数量
        redisUtil.set(redPacketId + "_num", String.valueOf(10));
        //初始化红包金额
        redisUtil.set(redPacketId + "_money", String.valueOf(100 * 100));
        /**
         * 模拟100个用户抢10个红包
         */

        for (int i = 1; i <= skillNum; i++) {
            int userId = i;
            Runnable task = () -> {
                /**
                 * 判断剩余金额
                 */
                Integer restMoney = Integer.valueOf((String) redisUtil.get(redPacketId + "_money"));
                if (restMoney > 0) {
                    /**
                     * 虽然能抢到，但是不一定可以拆到
                     * 类似于微信的 点击红包显示抢的按钮
                     */
                    Integer money = redPacketService.startTwoSeckil(redPacketId, userId);

                    Double amount = DoubleUtil.divide(Double.parseDouble(String.valueOf(money)), (double) 100);
                    log.info("用户{}抢红包成功，金额：{}", userId, amount);
                } else {
                    /**
                     * 直接显示手慢了，红包派完了
                     */
                }
                countDownLatch.countDown();
            };
            poolExecutor.execute(task);
        }
        try {
            countDownLatch.await();
            Integer restMoney = Integer.parseInt(redisUtil.get(redPacketId + "_money").toString());
            log.info("剩余金额：{}", restMoney);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
